<template>
	<view :id="elId" class="jp-tabs">
		<scroll-view id="scrollContainer" :scroll-x="scroll" :scroll-left="scroll ? scrollLeft : 0"
			:scroll-with-animation="scroll" :style="{ position: fixed ? 'fixed' : 'relative', zIndex }">
			<view class="jp-tabs__container" :style="[tabStyle,{
				display: scroll ? 'inline-flex' : 'flex',
				whiteSpace: scroll ? 'nowrap' : 'normal',
				height
			 }]">
				<view :class="['jp-tabs__container-item', { disabled: !!v.disabled },scroll?'':'scrollItem']"
					v-for="(v, i) in tabs" :key="i" :style="[current == i ?activeStyle:itmStyle]" @click="change(i)">
					{{ field ? v[field] : v }}
					<view v-if="corner&&v[corner]" class="corner" :style="[cornerStyle]">
						{{v[corner]}}
					</view>
				</view>

				<view v-if="!pills" :class="['jp-tabs__container-line', { animation: lineAnimation }]"
					:style="[lineStyle,{width: lineWidth + 'px',left: lineLeft + 'px',transform: `translateX(-${lineWidth / 2}px)` }]">
				</view>

				<view v-else :class="['jp-tabs__container-pills', { animation: lineAnimation }]" :style="[pillsStyle,{
					left: pillsLeft + 'px',
					width: currentWidth + 'px',
					height
				 }]"></view>

			</view>
		</scroll-view>
		<view class="jp-tabs__placeholder" :style="{
        height: fixed ? height : '0',
      }"></view>
	</view>
</template>

<script>
	/**
	 * jp-tabs
	 * @property {Number} value 选中的下标
	 * @property {Array} tabs tabs 列表
	 * @property {Boolean} scroll = [true | false] 是否滚动
	 * @property {String} height = '60rpx' tab 的高度
	 * @property {Number} lineScale = 0.5 下划线的宽度缩放比例
	 * @property {Boolean} pills = [true | false] 是否胶囊样式
	 * @property {String} field 如果是对象，显示的键名
	 * @property {Boolean} fixed = [true | false] 是否固定
	 * @property {Boolean} lineAnimation = [true | false] 下划线是否有动画
	 * @property {Number} zIndex = 1993 默认层级
	 * 
	 * 样式：
	 * tabStyle    tab样式
	 * activeStyle   选中样式
	 * itmStyle   未选中样式
	 * lineStyle  底部线条样式
	 * pillsStyle  卡片样式
	 * cornerStyle 角标样式
	 * 
	 * @event {Function(current)} change 改变标签触发
	 */
	export default {
		props: {
			value: {
				type: Number,
				default: 0
			},
			tabs: {
				type: Array,
				default () {
					return []
				}
			},
			height: { //'70rpx' tab 的高度
				type: String,
				default: '70rpx'
			},
			scroll: {
				type: Boolean,
				default: true
			},

			tabStyle: { // 选中样式
				type: [String, Object],
				default () {
					return {}
				}
			},

			activeStyle: { // 选中样式
				type: [String, Object],
				default () {
					return {
						color: '#23AAF2',
						padding: '0 20rpx'
					}
				}
			},
			itmStyle: { // 未选中样式
				type: [String, Object],
				default () {
					return {
						color: '#000',
						padding: '0 20rpx'
					}
				}
			},

			lineStyle: { // 底部线条样式
				type: [String, Object],
				default () {
					return {
						background: '#23AAF2',
						borderRadius: '2px',
						height: '2px',
					}
				}
			},
			lineScale: { // 下划线的宽度缩放比例
				type: Number,
				default: 0.6
			},


			pills: { // 是否卡片样式
				type: Boolean,
				default: false
			},
			pillsStyle: { // 卡片样式
				type: [String, Object],
				default () {
					return {
						background: '#f5f5f5',
						borderRadius: '2px'
					}
				}
			},
						
			corner	: { //角标键名
				type: String,
				default: ''
			},		
			cornerStyle: { // 卡片样式
				type: [String, Object],
				default () {
					return {
						background: '#f00',
						borderRadius: '50%',
						color: '#fff',
						fontSize: '12rpx',
						width: '30rpx',
						height: '30rpx'
					}
				}
			},

			field: { //如果是对象，显示的键名
				type: String,
				default: ''
			},
			lineAnimation: { //[true | false] 下划线是否有动画
				type: Boolean,
				default: true
			},

			fixed: { //fixed
				type: Boolean,
				default: false
			},
			zIndex: { //层级
				type: Number,
				default: 1999
			},


		},
		data() {
			return {
				elId: '',
				lineWidth: 30,
				currentWidth: 0, // 当前选项的宽度
				lineLeft: 0, // 滑块距离左侧的位置
				pillsLeft: 0, // 胶囊距离左侧的位置
				scrollLeft: 0, // 距离左边的位置
				containerWidth: 0, // 容器的宽度
				current: 0 // 当前选中项
			}
		},
		watch: {
			value(newVal) {
				this.current = newVal
				this.$nextTick(() => {
					this.getTabItemWidth()
				})
			},
			current(newVal) {
				this.$emit('input', newVal)
			},
			tabs(newVal) {
				this.$nextTick(() => {
					this.getTabItemWidth()
				})
			}
		},
		methods: {
			// 产生随机字符串
			randomString(len) {
				len = len || 32
				let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
				let maxPos = $chars.length
				let pwd = ''
				for (let i = 0; i < len; i++) {
					pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
				}
				return pwd
			},
			// 切换事件
			change(index) {
				const isDisabled = !!this.tabs[index].disabled
				if (this.current !== index && !isDisabled) {
					this.current = index

					this.$emit('change', index)
				}
			},
			// 获取左移动位置
			getTabItemWidth() {
				let query = uni
					.createSelectorQuery()
					// #ifndef MP-ALIPAY
					.in(this)
				// #endif
				// 获取容器的宽度
				query
					.select(`#scrollContainer`)
					.boundingClientRect((data) => {
						if (!this.containerWidth && data) {
							this.containerWidth = data.width
						}
					})
					.exec()
				// 获取所有的 tab-item 的宽度
				query
					.selectAll('.jp-tabs__container-item')
					.boundingClientRect((data) => {
						if (!data) {
							return
						}
						let lineLeft = 0
						let currentWidth = 0
						if (data) {
							for (let i = 0; i < data.length; i++) {
								if (i < this.current) {
									lineLeft += data[i].width
								} else if (i == this.current) {
									currentWidth = data[i].width
								} else {
									break
								}
							}
						}
						// 当前滑块的宽度
						this.currentWidth = currentWidth
						// 缩放后的滑块宽度
						this.lineWidth = currentWidth * this.lineScale * 1
						// 滑块作移动的位置
						this.lineLeft = lineLeft + currentWidth / 2
						// 胶囊距离左侧的位置
						this.pillsLeft = lineLeft
						// 计算滚动的距离左侧的位置
						if (this.scroll) {
							this.scrollLeft = this.lineLeft - this.containerWidth / 2
						}
					})
					.exec()
			}
		},
		mounted() {
			this.elId = 'jp_' + this.randomString()
			this.current = this.value
			this.$nextTick(() => {
				this.getTabItemWidth()
			})
		}
	}
</script>

<style lang="scss" scoped>
	.jp-tabs {
		width: 100%;
		box-sizing: border-box;
		overflow: hidden;
		

		::-webkit-scrollbar {
			display: none;
		}

		.scrollItem {
			justifyContent: 'center';
			flex: 1;
		}

		.scrollItemNo {}

		&__container {
			min-width: 100%;
			position: relative;
			display: inline-flex;
			align-items: center;
			white-space: nowrap;
			overflow: hidden;
			
			.corner{
				position: absolute;
				top: 0;
				right: 0;
				display: flex;
				justify-content: center;
				align-items: center;
			}

			&-item {
				display: flex;
				align-items: center;
				height: 100%;
				position: relative;
				z-index: 10;
				// padding: 0 11px;
				transition: all 0.3s;
				white-space: nowrap;

				&.disabled {
					opacity: 0.5;
					color: #999;
				}
			}

			&-line {
				position: absolute;
				bottom: 0;
			}

			&-pills {
				position: absolute;
				z-index: 9;
			}

			&-line,
			&-pills {
				&.animation {
					transition: all 0.3s linear;
				}
			}
		}
	}
</style>